﻿using Aliyun.OSS;
using OA.Core;
using OA.Core.Helper;
using OA.Model;
using OA.Model.View;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.AspNetCore.Http;
using OA.Model.Mapper;
using OA.Core.DataAccessHelper;

namespace OA.BLL
{
    public class ApprovalResult
    {
        public List<ApprovalItem> approvalItems { get; set; } 
    }



    public class CApproval : CBase
    {
        private IMemoryCache _cache;

        public CApproval(IMemoryCache memoryCache)
        {
            _cache = memoryCache;
        }


        public ApprovalResult GetApprovalResult(List<Department> listDepartment, List<Position> listPosition, List<Employee> listEmployee, List<VEmployeePosition> listEmployeePosition, CustomForm customForm, Voucher voucher, List<ApprovalItem> approvalItems, string positionLevel)
        {
            List<ApprovalNode> list = new List<ApprovalNode>();
            return GetApprovalResult(listDepartment, listPosition, listEmployee, listEmployeePosition, customForm, voucher, approvalItems, positionLevel, ref list);
        }

        /// <summary>
        /// 获取审批流程
        /// </summary>
        /// <param name="listDepartment"></param>
        /// <param name="listPosition"></param>
        /// <param name="listEmployee"></param>
        /// <param name="listEmployeePosition"></param>
        /// <param name="customForm"></param>
        /// <param name="voucher"></param>
        /// <param name="approvaItems">现有审批</param>
        /// <returns></returns>
        public ApprovalResult GetApprovalResult(List<Department> listDepartment, List<Position> listPosition, List<Employee> listEmployee, List<VEmployeePosition> listEmployeePosition, CustomForm customForm, Voucher voucher, List<ApprovalItem> approvalItems, string positionLevel,ref List<ApprovalNode> list)
        {
            ApprovalResult approvalResult = new ApprovalResult();//处理结果
            approvalResult.approvalItems = new List<ApprovalItem>();
            string endTime = DateTime.Now.ToString("yyyy-MM-dd");
            string currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            List<EmployeePosition> employeePositions = this.dbContextFactory.DbContext.EmployeePosition.Where(m => m.Status != -1 && m.EndTime.CompareTo(endTime) > 0).ToList();//获取所有有效成员岗位信息
            //获取工作委托
            var listDelegations = this.dbContextFactory.DbContext.MyDelegation.Where(m => m.Status == 1 && currentTime.CompareTo(m.StartTime) > 0 && currentTime.CompareTo(m.EndTime) < 0).ToList();
            Employee infoEmployee = listEmployee.Where(m => m.EmpID == voucher.Sponsor).FirstOrDefault();

            list = new List<ApprovalNode>();
            if (voucher.Status >= 1)
            {
                list = JsonHelper.DeserializeList<ApprovalNode>(voucher.ApprovalNodeContent);
            }
            else
            {
                list = this.GetFullApprovalPath(customForm, voucher, listEmployeePosition, infoEmployee, listPosition, listDepartment, positionLevel);//获取审核流程
            }
            if (list.Count == 0) { return approvalResult; }
           
            Queue<string> empIDs = new Queue<string>();
            for (int i= list.Count-1; i>=0;i--)
            {
                ApprovalNode node = list[i];
                if(!empIDs.Contains(node.EmpID))
                {           
                    empIDs.Enqueue(node.EmpID);
                }
                else
                {
                    node.Status = -1;
                }
            }
            var repeatNodes  = list.Where(m => m.Status == -1).ToList();
            list= list.Where(m => m.Status != -1).ToList();
            foreach (var repeatNode in repeatNodes)
            {
                if(list.Where(m => m.Step == repeatNode.Step).Count()==0)
                {
                    foreach (var item in list)
                    {
                        if(item.Step> repeatNode.Step)
                        {
                            item.Step = item.Step - 1;
                        }
                    }
                }
            }

            approvalResult.approvalItems.AddRange(approvalItems);//先附加已审核的

            for (int i = 0; i <= list.Count - 1; i++)
            {
                var item = list[i];
                ApprovalItem approvalItem = approvalItems.Where(m => m.ApprovalNodeID == item.NodeID && m.Step == item.Step).FirstOrDefault();
                if (approvalItem != null) continue; //如果是已经审核的就不处理
                approvalItem = new ApprovalItem();
                approvalItem.ApprovalNodeID = item.ID;
                approvalItem.DepartmentID = item.DepartmentID;
                approvalItem.DepartmentName = CDepartment.GetFullDepartmentNameByID(item.DepartmentID, listDepartment);
                var employee = CEmployee.GetEmployeeByPositionID(item.PositionID, listEmployeePosition);                 
                approvalItem.EmpID = employee.EmpID;
                approvalItem.EmpName = employee.EmpName;
                approvalItem.DepartmentID = item.DepartmentID;
                approvalItem.PositionID = item.PositionID;
                var delegation = listDelegations.Where(m => m.CustomFormID == voucher.CustomFormID && m.FromEmpID == employee.EmpID).FirstOrDefault();
                if (delegation != null)
                {
                    var delegationEmployee = CEmployee.GetEmployeeByEmpID(delegation.ToEmpID, listEmployee);
                    approvalItem.RealEmpID = delegationEmployee.EmpID;
                    approvalItem.RealEmpName = delegationEmployee.EmpName + "(代办)";
                    approvalItem.RealDepartmentID = delegation.ToDeparentID;
                    approvalItem.RealPositionID = delegation.ToPositionID;
                }
                else
                {
                    approvalItem.RealEmpID = employee.EmpID;
                    approvalItem.RealEmpName = employee.EmpName;
                    approvalItem.RealDepartmentID = item.DepartmentID;
                    approvalItem.RealPositionID = item.PositionID;
                }
                approvalItem.PointType = 1;
                approvalItem.PositionID = item.PositionID;
                approvalItem.PositionName = CPosition.GetPositionNameByID(item.PositionID, listPosition);
                approvalItem.Status = -1;
                approvalItem.Step = item.Step;
                approvalItem.ApprovalNodeID = item.NodeID;
                approvalItem.Pic = employee.Pic;
                approvalResult.approvalItems.Add(approvalItem);
            }
            return approvalResult;
        }


        public string CreateTableImage(MyDbContext dbContext, CacheHelper cacheHelper, Voucher infoVoucher, int customFormID, string empID)
        {
            //try
            //{
            //    var customForm = dbContext.CustomForm.Where(m => m.ID == customFormID).FirstOrDefault();

            //    CustomFormExtendInfo extendInfo = null;
            //    if (!string.IsNullOrWhiteSpace(infoVoucher.CustomFormContent))
            //    {
            //        extendInfo = JsonHelper.DeserializeObj<CustomFormExtendInfo>(infoVoucher.CustomFormContent);
            //    }
            //    else if (customForm != null && !string.IsNullOrWhiteSpace(customForm.ExtendField))
            //    {
            //        extendInfo = JsonHelper.DeserializeObj<CustomFormExtendInfo>(customForm.ExtendField);
            //    }
            //    if (extendInfo == null)
            //    {
            //        extendInfo = new CustomFormExtendInfo();
            //    }

            //    ExtensionResultInfo infoExtensionResult = new ExtensionResultInfo();
            //    if (!string.IsNullOrWhiteSpace(infoVoucher.Extension))
            //    {
            //        infoExtensionResult = JsonHelper.DeserializeObj<ExtensionResultInfo>(infoVoucher.Extension);
            //    }
            //    if (infoExtensionResult == null)
            //    {
            //        infoExtensionResult = new ExtensionResultInfo();
            //    }

            //    if (extendInfo != null && extendInfo.TableFields != null && extendInfo.TableFields.Count > 0 && infoExtensionResult != null && infoExtensionResult.TableValues != null && infoExtensionResult.TableValues.RowValues != null && infoExtensionResult.TableValues.RowValues.Count > 0)
            //    {
            //        string currentUrl = HttpContext.Current.Request.Url.ToString().ToLower();
            //        string[] items = currentUrl.Split(new string[] { "https://", "http://", "/" }, StringSplitOptions.RemoveEmptyEntries);
            //        string protocol = "http://";
            //        if (currentUrl.StartsWith("https://"))
            //        {
            //            protocol = "https://";
            //        }
            //        //生成表单快照
            //        int width = extendInfo.TableFields.Count * 60;
            //        int height = (infoExtensionResult.TableValues.RowValues.Count + 4) * 40;
            //        if (width < 800) { width = 800; }
            //        BaseConfig baseConfig = cacheHelper.GetConfig<BaseConfig>();
            //        string url = protocol + items[0] + $"/Home/ShowTable?id={infoVoucher.ID}&key={baseConfig.Token}";
            //        Bitmap m_Bitmap = WebSnapshotsHelper.GetWebSiteThumbnail(url, width, height, width, height); //宽高根据要获取快照的网页决定
            //        MemoryStream ms = new MemoryStream();
            //        m_Bitmap.Save(ms, ImageFormat.Png);
            //        ALiOSSConfig config = cacheHelper.GetConfig<ALiOSSConfig>();
            //        var client = new OssClient(config.Endpoint, config.AccessKeyId, config.AccessKeySecret);
            //        string key = $"Form/{customFormID}/{infoVoucher.ID}_{empID}.png";
            //        ms.Seek(0, SeekOrigin.Begin);
            //        client.PutObject(config.BucketName, key, ms);
            //        var imageUrl = string.Format("https://{0}.{1}/{2}", config.BucketName, config.Endpoint, key);
            //        return imageUrl;
            //    }
            //    else
            //    {
            //        return string.Empty;
            //    }
            //}
            //catch (Exception ex)
            //{
            //    return "error";
            //}

            return string.Empty;
        }

        /// <summary>
        /// 发起审批
        /// </summary>
        /// <param name="id">VoucherIDE</param>
        /// <returns></returns>
        public BaseResult Sponsor(int customID, int formID, Employee userInfo)
        {
            BaseResult result = new BaseResult();
            CacheHelper cacheHelper = new CacheHelper(_cache);
            List<Department> listDepartment = cacheHelper.GetDepartments();
            List<Position> listPosition = cacheHelper.GetPositions();
            List<Employee> listEmployee = cacheHelper.GetEmployees();
            List<VEmployeePosition> listEmployeePosition = cacheHelper.GetVEmployeePositions();

            var baseConfig= cacheHelper.GetConfig<BaseConfig>();

            string currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            var myDelegations = this.dbContextFactory.DbContext.MyDelegation.Where(m => m.CustomFormID == customID && m.Status == 1 && currentTime.CompareTo(m.StartTime) > 0 && currentTime.CompareTo(m.EndTime) < 0).ToList();

            VoucherMapper voucherMapper = new VoucherMapper();
            var dal = DataAccessor.Create<VoucherDbContext>();
            dal.ChangeMappingTable(typeof(Voucher), voucherMapper, customID);
            Voucher infoVoucher = dal.GetByID<Voucher>(formID);
            infoVoucher.CustomFormID = customID;
            if (infoVoucher == null || infoVoucher.Sponsor != userInfo.EmpID || infoVoucher.Status == -1)
            {
                result.State = 400;
                result.Msg = "发起审批失败,没有找到该单据信息";
                return result;
            }
            else if (infoVoucher.Status != 0)
            {
                result.State = 400;
                result.Msg = "发起审批失败,该单据当前状态信息为" + infoVoucher.StatusName + ",不允许发起审批";
                return result;
            }
            else//找到第一个审批人, 状态变1,写Approval
            {
                List<ApprovalNode> list = new List<ApprovalNode>();
                CustomForm customForm= this.dbContextFactory.GetInfo<CustomForm>(customID);
                ApprovalResult approvalResult = this.GetApprovalResult(listDepartment, listPosition, listEmployee, listEmployeePosition, customForm, infoVoucher, new List<ApprovalItem>(), baseConfig.PositionLevel,ref list);
                if (approvalResult.approvalItems.Count == 0)
                {
                    result.State = 400;
                    result.Msg = $"发起审批失败,没有找到开始节点,请检查对应的审批树";
                    return result;
                }
                List<ApprovalItem> newsItems = approvalResult.approvalItems.Where(m => m.Step == 1).ToList();
                foreach (var item in newsItems)
                {
                    item.PointType = 1;
                    if(newsItems.Count>1)//同一步骤有两人及以上，视为会签
                    {
                        item.PointType = 2;
                    }
                    item.IsPush = false;
                    item.Status = 0;
                    item.CreateDateTime = DateTime.Now;
                    
                    var itemEmpInfo = listEmployee.Where(m => m.EmpID == item.EmpID).FirstOrDefault();
                    if (itemEmpInfo != null)
                    {
                        item.EmpName = itemEmpInfo.EmpName;
                        item.Pic = itemEmpInfo.Pic;
                    }
                    
                    item.PositionName = listPosition.Where(m => m.ID == item.PositionID).Select(m => m.Name).FirstOrDefault();
                    item.DepartmentName = listDepartment.Where(m => m.ID == item.DepartmentID).Select(m => m.Name).FirstOrDefault();
                    
                    var myDelegation = myDelegations.Where(m => m.FromEmpID == item.EmpID).FirstOrDefault();
                    if(myDelegation!=null)
                    {                        
                        item.RealDepartmentID = myDelegation.ToDeparentID;                        
                        item.RealEmpID = myDelegation.ToEmpID;
                        itemEmpInfo = listEmployee.Where(m => m.EmpID == item.RealEmpID).FirstOrDefault();
                        if(itemEmpInfo!=null)
                        {
                            item.Pic = itemEmpInfo.Pic;
                        }
                        item.RealPositionID = myDelegation.ToPositionID;
                        item.RealPositionName = listPosition.Where(m => m.ID == myDelegation.ToPositionID).Select(m => m.Name).FirstOrDefault(); ;
                        item.RealEmpName = myDelegation.ToEmpName;
                        item.RealDepartmentName = listDepartment.Where(m => m.ID == myDelegation.ToDeparentID).Select(m => m.Name).FirstOrDefault();
                    }
                    else
                    {
                        item.RealEmpName = item.EmpName;
                        item.RealDepartmentID = item.DepartmentID;
                        item.RealDepartmentName = item.DepartmentName;
                        item.RealEmpID = item.EmpID;
                        item.RealPositionID = item.PositionID;
                        item.RealPositionName = item.PositionName;
                        
                    }
                }                 

                Approval approval = new Approval();
                approval.ApprovalItem = newsItems;
                approval.CreateDateTime = DateTime.Now;
                approval.CustomID = customID;
                approval.FormID = formID;
                approval.No = infoVoucher.No;
                
                approval.SponsorEmpID = infoVoucher.Sponsor;
                approval.SponsorPositionID = infoVoucher.PositionID;
                approval.Status = 1;
                approval.Suspense = newsItems.Select(m => m.RealEmpName).ToList().ToJsonString();
                approval.SuspenseEmpID= newsItems.Select(m => m.EmpID).ToList().ToJsonString();
                approval.Synchronization = 0;
                approval.Title = infoVoucher.Title;
                 
                infoVoucher.Status = 1;
                infoVoucher.ApplicationDate = DateTime.Now;
                infoVoucher.ApprovalNodeContent = JsonHelper.SerializeObject(list);
                var dbContext = dal.GetDbContext();
                using (var trn = dbContext.Database.BeginTransaction())
                {
                    try
                    {

                        dbContext.Set<Approval>().Add(approval);
                        dal.Save();
                        infoVoucher.ApprovalID = approval.ID;
                        dbContext.Set<Voucher>().Update(infoVoucher);
                        dal.Save();
                        trn.Commit();
                    }
                    catch (Exception ex)
                    {
                        trn.Rollback();
                        result.State = 400;
                        result.Msg = $"发起审批失败,系统异常！请重试";
                        return result;
                    }
                }
            }
            return result;
        }

        public Dictionary<string,string> InintExtensionResultByVoucher(Voucher infoVoucher,Employee infoEmployee)
        {

            Dictionary<string, string> result = new Dictionary<string, string>();

            List<ExtendField> infoExtensionResult = JsonHelper.DeserializeList<ExtendField>(infoVoucher.CustomFormContent);
            if (!string.IsNullOrWhiteSpace(infoVoucher.Extension))
            {
                result = JsonHelper.DeserializeObj<Dictionary<string, string>>(infoVoucher.Extension);
            }

            if (!result.Keys.Contains("Sponsor"))
            {
                result.Add("Sponsor", infoVoucher.Sponsor);
            }

            if (!result.Keys.Contains("DepartmentID"))
            {
                result.Add("DepartmentID", infoVoucher.DepartmentID.ToString());
            }

            result.Add("VirtualLevel", infoEmployee.VirtualPositionLevel);

            var listDepartment = this.dbContextFactory.DbContext.Department.Where(m => m.Status != -1).Select(SimpleDepartment.Map).ToList();
            List<int> Departments = CDepartment.GetFullDepartmentIDByID(infoVoucher.PositionID, listDepartment);
            for (int i = 0; i < Departments.Count; i++)
            {
                if (!result.Keys.Contains($"DepartmentID_{i}"))
                {
                    result.Add($"DepartmentID_{i}", Departments[i].ToString());
                }
            }



            if (!result.Keys.Contains("PositionID"))
            {
                result.Add("PositionID", infoVoucher.PositionID.ToString());
            }
            var tableResults = infoExtensionResult.Where(m => m.Type==99).ToList();
            if (tableResults.Count > 0)
            {
                foreach(var tableResult in tableResults)
                {
                    decimal total = 0;
                    if(result.ContainsKey(tableResult.Attribute))
                    {
                        var list = JsonHelper.DeserializeList<Dictionary<string, string>>(result[tableResult.Attribute]);
                        foreach (var rowValue in list)
                        {
                            foreach (var cellValues in rowValue)
                            {
                                string key = tableResult.Attribute + "_" + cellValues.Key;
                                string value = cellValues.Value;

                                if (result.ContainsKey(key))
                                {
                                    result[key] = result[key] + "@^@" + value;//列数据连接
                                }
                                else
                                {
                                    result.Add(key, value);
                                }
                                if (cellValues.Key == "SubTotal")//小计
                                {
                                    decimal subTotal = 0;
                                    if (decimal.TryParse(value, out subTotal))
                                    {
                                        total += subTotal;
                                    }
                                }
                            }
                        }
                        result.Add(tableResult.Attribute + "__Total", total.ToString());
                    }                    
                }
            }

            return result;
        }

        /// <summary>
        /// 获取审批流程节点
        /// </summary>
        /// <param name="infoVoucher"></param>
        /// <returns></returns>
        public List<ApprovalNode> GetFullApprovalPath(CustomForm customForm, Voucher infoVoucher, List<VEmployeePosition> employeePositions,Employee infoEmployee,List<Position> positions, List<Department> departments,string positionLevel)
        { 

            string[] positionLevels = positionLevel.Split(new string[] { ",","，"},StringSplitOptions.RemoveEmptyEntries);
            var listPositionLevel = positionLevels.ToList();
            List<ApprovalNode> myApprovalNodes = new List<ApprovalNode>();
            if(customForm.IsCustomProcess) //自定义流程
            {
                var customProcessNodes = JsonHelper.DeserializeList<CustomProcessNode>(infoVoucher.TreeContent);
                foreach (var item in customProcessNodes)
                {
                    ApprovalNode approvalNode = new ApprovalNode();
                    approvalNode.Conditions = "[]";
                    approvalNode.Countersign = "";
                    approvalNode.CreateDateTime = DateTime.Now;
                    approvalNode.CustomFormID = customForm.ID;
                    approvalNode.DepartmentID = item.DepartmentID;
                    approvalNode.EmpID = item.EmpID;
                    approvalNode.EmpName = item.EmpName;
                    approvalNode.Name = item.EmpID;
                    approvalNode.NodeID = 0;
                    approvalNode.NodeName = "自定义流程";
                    approvalNode.PositionID = item.PositionID;
                    approvalNode.Status = 0;
                    approvalNode.Step = item.Setp;
                    approvalNode.TypeID = 1;
                    approvalNode.ID = item.PositionID;
                    myApprovalNodes.Add(approvalNode);
                }

                return myApprovalNodes;
            }

            var infoExtensionResult = InintExtensionResultByVoucher(infoVoucher, infoEmployee);

            List<ApprovalProcessNodeInfo> listApprovalNode = JsonHelper.DeserializeList<ApprovalProcessNodeInfo>(customForm.ApprovalProcessNodeContent);
            if (listApprovalNode.Count == 0)
            {
                return myApprovalNodes;
            }
            int index = 1;
            foreach (var node in listApprovalNode)
            {
                if(node.Type==1&& node.Positions!=null)
                {
                    List<ApprovalNode> positionNodes = new List<ApprovalNode>();
                    foreach (var position in node.Positions)
                    {
                        if(ConditionsOfSatisfaction(node.Filters, infoExtensionResult, position, listPositionLevel))
                        {
                            VEmployeePosition currentEmployeePosition = employeePositions.Where(m => m.PositionID == position).FirstOrDefault();
                            if (currentEmployeePosition == null) continue;
                            ApprovalNode approvalNode = new ApprovalNode();

                            approvalNode.Name = currentEmployeePosition.Honor;
                            approvalNode.EmpID = currentEmployeePosition.EmpID;
                            approvalNode.EmpName = currentEmployeePosition.EmpName;
                            approvalNode.DepartmentID = currentEmployeePosition.DepartmentID;
                            approvalNode.PositionID = currentEmployeePosition.PositionID;


                            approvalNode.CreateDateTime = DateTime.Now;
                            approvalNode.CustomFormID = infoVoucher.CustomFormID;
                            approvalNode.NodeID = position;
                            approvalNode.NodeName = node.Name;
                            if (node.HideAttribute != null && node.HideAttribute.Count > 0)
                            {
                                approvalNode.PrivacyFields = string.Join(",", node.HideAttribute);
                            }
                            if (node.AbledEditAttribute != null && node.AbledEditAttribute.Count > 0)
                            {
                                approvalNode.EnableEditableFields = string.Join(",", node.AbledEditAttribute);
                            }
                            approvalNode.TypeID = 1;
                            approvalNode.Step = index;
                            approvalNode.Status = 1;
                            positionNodes.Add(approvalNode);
                        }
                    }
                    if (positionNodes.Count > 1)//如果多个岗位满足这一步，则设为会签
                    {
                        positionNodes.ForEach(m => m.TypeID = 2);
                    }
                    myApprovalNodes.AddRange(positionNodes);
                    index++;
                }
                else if(node.Type==2&& infoVoucher.CustomProcessNodes != null)
                {
                    List<ApprovalNode> huiQianNodes = new List<ApprovalNode>();
                    foreach (var countersign in infoVoucher.CustomProcessNodes)
                    {
                        VEmployeePosition currentEmployeePosition = employeePositions.Where(m => m.DepartmentID == countersign.DepartmentID&&m.EmpID== countersign.EmpID).FirstOrDefault();
                        if (currentEmployeePosition==null) continue;
                        ApprovalNode approvalNode = new ApprovalNode();

                        approvalNode.Name = currentEmployeePosition.Honor;
                        approvalNode.EmpID = currentEmployeePosition.EmpID;
                        approvalNode.EmpName = currentEmployeePosition.EmpName;
                        approvalNode.DepartmentID = currentEmployeePosition.DepartmentID;
                        approvalNode.PositionID = currentEmployeePosition.PositionID;


                        approvalNode.CreateDateTime = DateTime.Now;
                        approvalNode.CustomFormID = infoVoucher.CustomFormID;
                        approvalNode.NodeID = currentEmployeePosition.PositionID;
                        approvalNode.NodeName = node.Name;
                        if (node.HideAttribute!=null&& node.HideAttribute.Count > 0)
                        {
                            approvalNode.PrivacyFields = string.Join(",", node.HideAttribute);
                        }
                        if (node.AbledEditAttribute != null && node.AbledEditAttribute.Count > 0)
                        {
                            approvalNode.EnableEditableFields = string.Join(",", node.AbledEditAttribute);
                        }
                        approvalNode.TypeID = 2;
                        approvalNode.Step = index;
                        approvalNode.Status = 1;
                        huiQianNodes.Add(approvalNode);
                    }
                    myApprovalNodes.AddRange(huiQianNodes);
                    index++;
                }
                else if(node.Type==3)//组织上的上级，每个部门可以设置2个负责人，第一个负责人级别高于第2个负责人
                {
                    List<ApprovalNode> jiCengNode = new List<ApprovalNode>();
                    int positionID = infoVoucher.PositionID;
                    var positionInfo = positions.Where(m => m.ID == positionID).FirstOrDefault();
                    int departmentID = 0;
                    if(positionInfo!=null)
                    {
                        departmentID = positionInfo.DepartmentID;                        
                    }
                    int setLevel= Array.IndexOf(positionLevels, node.LastPositionLevel);
                    int tempIndex = 0;
                    while (tempIndex<10)
                    {
                        if (departmentID == 0) break;
                        var departmentInfo = departments.Where(m => m.ID == departmentID).FirstOrDefault();
                        departmentID = departmentInfo.ParentDepartmentID;                        
                        if (departmentInfo!=null&& departmentInfo.LeaderPositionID != positionID)
                        {
                            List<int> leaderPositions = new List<int>();
                            if(departmentInfo.LeaderPositionID2!=null&& departmentInfo.LeaderPositionID2!= departmentInfo.LeaderPositionID&&departmentInfo.LeaderPositionID2 > 0 && departmentInfo.LeaderPositionID2 != positionID)
                            {
                                leaderPositions.Add(departmentInfo.LeaderPositionID2 ?? 0);
                            }
                            if (departmentInfo.LeaderPositionID > 0)
                            {
                                leaderPositions.Add(departmentInfo.LeaderPositionID);
                            }

                            foreach (var leaderPosition in leaderPositions)
                            {
                                VEmployeePosition ep = employeePositions.Where(m => m.PositionID == leaderPosition && m.Status == 1).FirstOrDefault();
                                if (ep != null)
                                {
                                    int currentLevel = 999;

                                    if (!string.IsNullOrWhiteSpace(ep.Level))
                                    {
                                        currentLevel = Array.IndexOf(positionLevels, ep.Level);
                                    }

                                    if (currentLevel >= setLevel || (node.AtLeastOneSuperior && jiCengNode.Count == 0))
                                    {
                                        ApprovalNode approvalNode = new ApprovalNode();

                                        approvalNode.Name = ep.Honor;
                                        approvalNode.EmpID = ep.EmpID;
                                        approvalNode.EmpName = ep.EmpName;
                                        approvalNode.DepartmentID = ep.DepartmentID;
                                        approvalNode.PositionID = ep.PositionID;


                                        approvalNode.CreateDateTime = DateTime.Now;
                                        approvalNode.CustomFormID = infoVoucher.CustomFormID;
                                        approvalNode.NodeID = ep.PositionID;

                                        if (node.HideAttribute != null && node.HideAttribute.Count > 0)
                                        {
                                            approvalNode.PrivacyFields = string.Join(",", node.HideAttribute);
                                        }
                                        if (node.AbledEditAttribute != null && node.AbledEditAttribute.Count > 0)
                                        {
                                            approvalNode.EnableEditableFields = string.Join(",", node.AbledEditAttribute);
                                        }
                                        approvalNode.TypeID = 3;
                                        approvalNode.Step = index;
                                        approvalNode.Status = 1;
                                        jiCengNode.Add(approvalNode);
                                        index++;
                                    }
                                    else
                                    {
                                        break;
                                    }

                                }
                            }
                        }
                        tempIndex++;
                    }
                    myApprovalNodes.AddRange(jiCengNode);
                }
                
            }
 
            return myApprovalNodes;
        }


        /// <summary>
        /// 判断表单项是否满足审批节点条件
        /// </summary>
        /// <param name="list">条件LIst</param>
        /// <param name="infoExtensionResult">单据数据</param>
        /// <param name="employeePositions"></param>
        /// <param name="position">如果条件中包含审批人的过滤。可能会返回审批人</param>
        /// <returns></returns>
        public bool ConditionsOfSatisfaction(List<Filter> list, Dictionary<string,string> infoExtensionResult,int position,List<string> levels)
        {
            if (list == null || list.Count == 0) return true;
            var groups = list.GroupBy(m => m.GroupID).ToList();//条件分组 同一组条件之间是And 不同组之间是OR
            //VirtualLevel
            foreach (var item in groups)
            {
                bool flag = true;
                foreach (var condition in item)
                {
                    ///按审核人过滤
                    if(condition.Attribute== "Approver")//由审批岗位和条件构成一个整体条件
                    {
                        int selectApprover = 0;
                        if(!Int32.TryParse(condition.Value,out selectApprover))
                        {
                            flag = false;
                            break;
                        }
                        else if(selectApprover!=position)
                        {
                            flag = false;
                            break;
                        }
                    }
                    else if(condition.Attribute== "VirtualLevel")//虚拟级层对比
                    {
                        string value = infoExtensionResult[condition.Attribute];

                        if (condition.Type<6)//对比
                        {
                            int currentIndex = levels.IndexOf(value);
                            int compareIndex = levels.IndexOf(condition.Value);
                            if(compareIndex==-1|| currentIndex == -1)
                            {
                                flag = false;
                                break;
                            }
                            if (condition.Type == 1)//小于
                            {
                                if (compareIndex <= currentIndex)
                                {
                                    flag = false;
                                    break;
                                }

                            }
                            else if (condition.Type == 2)//小于等于
                            {
                                if (compareIndex < currentIndex)
                                {
                                    flag = false;
                                    break;
                                }

                            }
                            else if (condition.Type == 3)//等于
                            {
                                if (condition.Value != value)
                                {
                                    flag = false;
                                    break;
                                }
                            }
                            else if (condition.Type == 4)//大于等于
                            {
                                if (compareIndex > currentIndex)
                                {
                                    flag = false;
                                    break;
                                }

                            }
                            else if (condition.Type == 5)//大于
                            {
                                if (compareIndex >= currentIndex)
                                {
                                    flag = false;
                                    break;
                                }
                            }                           
                        }
                        else if(condition.Type==6|| condition.Type==7)
                        {
                            if (string.IsNullOrWhiteSpace(condition.Value))
                            {
                                flag = false;
                                break;
                            }
                            else
                            {
                                var values = condition.Value.Split(new string[] { ",", "，" }, StringSplitOptions.RemoveEmptyEntries).ToList();
                                if (condition.Type == 6)
                                {
                                    if (!values.Contains(value))
                                    {
                                        flag = false;
                                        break;
                                    }

                                }
                                else if (condition.Type == 7)
                                {
                                    if (values.Contains(value))
                                    {
                                        flag = false;
                                        break;
                                    }

                                }
                            }
                        }
                    }
                    else if (infoExtensionResult.Keys.Contains(condition.Attribute))
                    {
                        string value = infoExtensionResult[condition.Attribute];
                        List<int> decimalType = new List<int>{ 1, 2, 4, 5 };
                        decimal numberValue = 0;//单据的值
                        decimal conditionValue = 0;//条件判断的值
                        if(decimalType.Contains(condition.Type))
                        {
                            if (!Decimal.TryParse(value, out numberValue))
                            {
                                flag = false;
                                break;
                            }
                            if (!Decimal.TryParse(condition.Value, out conditionValue))
                            {
                                flag = false;
                                break;
                            }
                        }                      

                        if (condition.Type == 1)//小于
                        {
                            if(conditionValue<= numberValue)
                            {
                                flag = false;
                                break;
                            }
                           
                        }
                        else if (condition.Type == 2)//小于等于
                        {
                            if(conditionValue < numberValue)
                            {
                                flag = false;
                                break;
                            }
                            
                        }
                        else if (condition.Type == 4)//大于等于
                        {
                            if(conditionValue > numberValue)
                            {
                                flag = false;
                                break;
                            }
                            
                        }
                        else if (condition.Type == 5)//大于
                        {
                            if(conditionValue >= numberValue)
                            {
                                flag = false;
                                break;
                            }
                            
                        }
                        else if(condition.Type==3)//等于
                        {
                            if(condition.Value!=value)
                            {
                                if (!Decimal.TryParse(value, out numberValue))
                                {
                                    flag = false;
                                    break;
                                }
                                if (!Decimal.TryParse(condition.Value, out conditionValue))
                                {
                                    flag = false;
                                    break;
                                }
                                if(numberValue!= conditionValue)
                                {
                                    flag = false;
                                    break;
                                }
                            }
                        }
                        else if (condition.Type == 6|| condition.Type == 7)//包含+不包含
                        {
                            if(string.IsNullOrWhiteSpace(condition.Value))
                            {
                                flag = false;
                                break;
                            }
                            else
                            {
                                var values= condition.Value.Split(new string[] { ",","，"},StringSplitOptions.RemoveEmptyEntries).ToList();
                                if(condition.Type == 6)
                                {
                                    if(!values.Contains(value))
                                    {
                                        flag = false;
                                        break;
                                    }
                                    
                                }
                                else if (condition.Type == 7)
                                {
                                    if(values.Contains(value))
                                    {
                                        flag = false;
                                        break;
                                    }
                                    
                                }
                            }
                        }
                         
                    }
                    else
                    {
                        flag = false;
                        break;
                    }
                }

                if (flag)
                {
                    return true;
                }
            }

            return false;
        }

        

        /// <summary>
        /// 处理单据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <param name="explain"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public BaseResult Conduct(DataAccessor dal,int os, Employee userInfo,Approval infoApproval, ApprovalItem infoApprovalItem, CustomForm customForm, Voucher infoVoucher, Dictionary<string, string> dicExtend)
        {
            BaseResult result = new BaseResult();
            CacheHelper cacheHelper = new CacheHelper(_cache);
            List<Department> listDepartment = cacheHelper.GetDepartments();
            List<Position> listPosition = cacheHelper.GetPositions();
            List<Employee> listEmployee = cacheHelper.GetEmployees();
            List<VEmployeePosition> listEmployeePosition = cacheHelper.GetVEmployeePositions();

            var baseConfig = cacheHelper.GetConfig<BaseConfig>();

            var approvalItems = this.dbContextFactory.DbContext.ApprovalItem.Where(m => m.ApprovalID== infoApprovalItem.ApprovalID).ToList();
            List<ApprovalNode> nodes = new List<ApprovalNode>();
            ApprovalResult approvalResult = this.GetApprovalResult(listDepartment, listPosition, listEmployee, listEmployeePosition, customForm, infoVoucher, approvalItems, baseConfig.PositionLevel,ref nodes);
            if (approvalResult.approvalItems.Count == 0)
            {
                result.State = 400;
                result.Msg = "当前审批单据没有找到任何审批节点";
                return result;
            }

            ApprovalNode infoProcessPoint = nodes.Where(m => m.Step == infoApprovalItem.Step && m.NodeID == infoApprovalItem.ApprovalNodeID).FirstOrDefault();

            if (string.IsNullOrWhiteSpace(infoApproval.Suspense)) { infoApproval.Suspense = ""; }
            if (string.IsNullOrWhiteSpace(infoApproval.NeedExplainEmpID)) { infoApproval.NeedExplainEmpID = ""; }
            DateTime now = DateTime.Now;

            infoApprovalItem.ApprovalTime = now;
            if(infoProcessPoint.TypeID==2)//会签
            {
                infoApprovalItem.Status = 2;
            }
            else
            {
                infoApprovalItem.Status = 3;
            }

            HttpContextAccessor context = new HttpContextAccessor();
            var ip = context.HttpContext?.Connection.RemoteIpAddress.ToString();
            infoApprovalItem.IP = ip;
            infoApprovalItem.OS = os;


            #region 同意/会签     

            if (!string.IsNullOrWhiteSpace(infoApproval.Suspense))
            {
                infoApproval.Suspense = infoApproval.Suspense.Replace(infoApprovalItem.EmpName + ",", "").Replace("," + infoApprovalItem.EmpName, "").Replace(infoApprovalItem.EmpName, "");
            }

            if(!string.IsNullOrWhiteSpace(infoApproval.NeedExplainEmpID))
            {
                infoApproval.NeedExplainEmpID = infoApproval.NeedExplainEmpID.Replace(infoApprovalItem.EmpName + ",", "").Replace("," + infoApprovalItem.EmpName, "").Replace(infoApprovalItem.EmpName, "");
            }

            List<string> updateField = new List<string>();
            if(!string.IsNullOrWhiteSpace(infoProcessPoint.EnableEditableFields))
            {
                updateField = infoProcessPoint.EnableEditableFields.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList();
            }

             
            if (updateField.Count>0)//修改数据   _E-__O,_E-__P,_E-__Q,_E-__R,_E-__S
            {
                List<ExtendField> extensions = new List<ExtendField>();
                if (!string.IsNullOrWhiteSpace(infoVoucher.Extension))
                {
                    extensions = JsonHelper.DeserializeList<ExtendField>(infoVoucher.CustomFormContent);
                }
                Dictionary<string,string> reuslt= JsonHelper.DeserializeObj<Dictionary<string, string>>(infoVoucher.Extension);
                foreach (var key in dicExtend.Keys)
                {
                    var extension = extensions.Where(m => m.Attribute == key).FirstOrDefault();
                    if (extension != null)
                    {
                        if (extension.Type != 99)
                        {
                            if (updateField.Contains(key))
                            {
                                if (reuslt.ContainsKey(key))
                                {
                                    reuslt[key] = dicExtend[key];
                                }
                                else
                                {
                                    reuslt.Add(key, dicExtend[key]);
                                }
                            }                            
                        }
                        else//表格
                        {
                            List<Dictionary<string, string>> newTableValues = JsonHelper.DeserializeObj<List<Dictionary<string, string>>>(dicExtend[key]);
                            List<Dictionary<string, string>> oldTableValues = new List<Dictionary<string, string>>();
                            List<ExtensionResultItem> tableExtensions = JsonHelper.DeserializeList<ExtensionResultItem>(extension.DefaultValue);
                            if (reuslt.ContainsKey(key))
                            {
                                oldTableValues = JsonHelper.DeserializeObj<List<Dictionary<string, string>>>(reuslt[key]);
                            }
                            if(oldTableValues.Count== newTableValues.Count)
                            {
                                for (int i = 0; i < newTableValues.Count; i++)
                                {
                                    Dictionary<string, string> newDic = newTableValues[i];
                                    Dictionary<string, string> oldDic = oldTableValues[i];

                                    foreach (var tdKey in newDic.Keys)
                                    {
                                        string tempKey = extension.Attribute + "-" + tdKey;
                                        if (updateField.Contains(tempKey))
                                        {
                                            if(oldDic.ContainsKey(tdKey))
                                            {
                                                oldDic[tdKey] = newDic[tdKey];
                                            }
                                            else
                                            {
                                                oldDic.Add(tdKey, newDic[tdKey]);
                                            }
                                        }
                                    }

                                }

                            }
                            reuslt[key] = JsonHelper.SerializeObject(oldTableValues);

                        }
                    }
                    infoVoucher.Extension = JsonHelper.SerializeObject(reuslt);
                }
            }

            #endregion

            if (infoApprovalItem.PointType == 2)//会签,一般不更新数据  0：待审核 1：需要说明 2：审核通过  3:审核不同意
            {
                var untreateds = this.dbContextFactory.DbContext.ApprovalItem.Where(m => m.ApprovalID == infoApproval.ID && m.Status <= 0).Select(m => m.ID).Count();
                if (untreateds > 1)//会签，并且还有其他审批节点
                {
                    using (var trn = this.dbContextFactory.DbContext.Database.BeginTransaction())
                    {
                        try
                        {
                            if (updateField.Count > 0)
                            {
                                dal.Update<Voucher>(infoVoucher);
                            }
                            dal.Update<Approval>(infoApproval);
                            dal.Update<ApprovalItem>(infoApprovalItem);
                            dal.Save();
                            trn.Commit();
                        }
                        catch(Exception ex)
                        {
                            result.State = 400;
                            result.Msg = "非法的提交!请联系管理员";
                            trn.Rollback();
                        }

                    }
                    return result;
                }
            }

            int nextStep = infoApprovalItem.Step + 1;
            List<ApprovalItem> nextNodes = approvalResult.approvalItems.Where(m => m.Step == nextStep).ToList();
            if (nextNodes.Count == 0)//下一个节点不存在
            {
                infoVoucher.Status = 4;
                infoVoucher.FinishTime = now;                          
                using (var trn = this.dbContextFactory.DbContext.Database.BeginTransaction())
                {
                    try
                    {            
                        infoVoucher.FinishTime = now;                        
                        infoApproval.FinishTime = now;
                        infoApproval.Status = 4;
                        infoApproval.NeedExplainEmpID = "";
                        infoApproval.Suspense = "";
                        List<CallBackInfo> callBacks = new List<CallBackInfo>();
                        if (!string.IsNullOrWhiteSpace(customForm.CallBackUrl) && customForm.CallBackUrl.Length>5)
                        {
                            var callBackUrls = customForm.CallBackUrl.Split(new string[] { ",", "，" }, StringSplitOptions.RemoveEmptyEntries).ToList();
                            
                            foreach (var url in callBackUrls)
                            {
                                if(CommonHelper.IsUrl(url))
                                {
                                    CallBackInfo callBackInfo = new CallBackInfo();
                                    callBackInfo.Status = 0;
                                    callBackInfo.CustomID = infoApproval.CustomID;
                                    callBackInfo.FormID= infoVoucher.ID;
                                    callBackInfo.Url = url;
                                    callBacks.Add(callBackInfo);
                                }                               
                            }                             
                        }
                        if (updateField.Count > 0)
                        {
                            dal.Update<Voucher>(infoVoucher);
                        }
                        dal.Update<Voucher>(infoVoucher);
                        dal.Update<Approval>(infoApproval);
                        dal.Update<ApprovalItem>(infoApprovalItem);
                        if (callBacks.Count > 0)
                        {
                            dal.GetDbContext().Set<CallBackInfo>().AddRange(callBacks);
                        }                        
                        dal.Save();
                        trn.Commit();
                    }
                    catch (Exception ex)
                    {
                        trn.Rollback();
                        result.State = 400;
                        result.Msg = "数据库操作异常,请报告系统管理员";
                    }
                    return result;
                }
            }
            else
            {
                string currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                var myDelegations = this.dbContextFactory.DbContext.MyDelegation.Where(m => m.CustomFormID == infoApproval.CustomID && m.Status == 1 && currentTime.CompareTo(m.StartTime) > 0 && currentTime.CompareTo(m.EndTime) < 0).ToList();

                foreach (var item in nextNodes)
                {
                    item.Status = 0;
                    item.CreateDateTime = DateTime.Now;
                    var empInfo = listEmployee.Where(m => m.EmpID == item.EmpID).FirstOrDefault();
                    if(empInfo!=null)
                    {
                        item.EmpName = empInfo.EmpName;
                        item.Pic = empInfo.Pic;
                    }                     
                    item.PositionName = listPosition.Where(m => m.ID == item.PositionID).Select(m => m.Name).FirstOrDefault();
                    item.DepartmentName = listDepartment.Where(m => m.ID == item.DepartmentID).Select(m => m.Name).FirstOrDefault();
                    item.ApprovalID = infoApproval.ID;

                    var myDelegation = myDelegations.Where(m => m.FromEmpID == item.EmpID).FirstOrDefault();
                    if (myDelegation != null)
                    {

                        item.RealDepartmentID = myDelegation.ToDeparentID;
                        item.RealEmpID = myDelegation.ToEmpID;
                        empInfo = listEmployee.Where(m => m.EmpID == item.RealEmpID).FirstOrDefault();
                        if (empInfo != null)
                        {
                            item.Pic = empInfo.Pic;
                        }
                        item.RealPositionID = myDelegation.ToPositionID;
                        item.RealPositionName = listPosition.Where(m => m.ID == myDelegation.ToPositionID).Select(m => m.Name).FirstOrDefault(); ;
                        item.RealEmpName = myDelegation.ToEmpName;
                        item.RealDepartmentName = listDepartment.Where(m => m.ID == myDelegation.ToDeparentID).Select(m => m.Name).FirstOrDefault();
                    }
                    else
                    {
                        item.RealEmpName = item.EmpName;
                        item.RealDepartmentID = item.DepartmentID;
                        item.RealDepartmentName = item.DepartmentName;
                        item.RealEmpID = item.EmpID;
                        item.RealPositionID = item.PositionID;
                        item.RealPositionName = item.PositionName;
                    }
                }
                var dbContext = dal.GetDbContext();
                using (var trn = dbContext.Database.BeginTransaction())
                {
                    try
                    {
                        infoApproval.ApprovalItem = null;
                        infoApproval.Suspense = JsonHelper.SerializeObject(nextNodes.Select(m => m.RealEmpName).ToList());
                        dbContext.Set<ApprovalItem>().AddRange(nextNodes);
                        dal.Update<Voucher>(infoVoucher);
                        dal.Update<Approval>(infoApproval);
                        dal.Update<ApprovalItem>(infoApprovalItem);
                        dal.Save();
                        trn.Commit();
                        return result;
                    }
                    catch (Exception ex)
                    {
                        trn.Rollback();
                        result.State = 400;
                        result.Msg = "数据库操作异常,请报告系统管理员";
                    }
                    return result;
                }

            }
        }       
    }
}
